package cn.wp.ewallet.wallet.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.wp.common.core.authentication.AuthenticationContext;
import cn.wp.common.core.authentication.AuthenticationInfo;
import cn.wp.common.core.util.BCryptPasswordEncoder;
import cn.wp.common.core.util.BeanUtil;
import cn.wp.ewallet.wallet.dao.WalletInfoDao;
import cn.wp.ewallet.wallet.extension.constant.EwalletWalletConstant;
import cn.wp.ewallet.wallet.extension.util.DesUtil;
import cn.wp.ewallet.wallet.extension.util.EwalletWalletUtil;
import cn.wp.ewallet.wallet.model.dto.*;
import cn.wp.ewallet.wallet.model.entity.WalletAccountInfoDoo;
import cn.wp.ewallet.wallet.model.entity.WalletInfoDo;
import cn.wp.ewallet.wallet.service.AccountInfoService;
import cn.wp.ewallet.wallet.service.UserWalletRelService;
import cn.wp.ewallet.wallet.service.WalletInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.web3j.crypto.*;
import org.web3j.utils.Numeric;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

import static cn.wp.ewallet.wallet.extension.constant.EwalletWalletConstant.ACCOUNT_TYPE_AVAILABLE;
import static cn.wp.ewallet.wallet.extension.constant.EwalletWalletConstant.ACCOUNT_TYPE_WEB;


/**
 * 钱包-业务逻辑层实现
 * Created by zhangyongli on 2020/01/08
 */
@Slf4j
@Service
public class WalletInfoServiceImpl implements WalletInfoService {

    @Autowired
    private WalletInfoDao walletInfoDao;

    @Autowired
    private AccountInfoService accountInfoService;

    @Autowired
    private UserWalletRelService userWalletRelService;

    @Autowired
    private AuthenticationContext authenticationContext;

    /**
     * 钱包创建流程
     *  1、创建区块链钱包；
     *  2、保存钱包信息；
     *  3、生产账户信息：-- USDT账户（可用资产），SHQC账户（可用资产，定期理财，天天盈理财）
     *  4、关联用户账户和地址；
     *  5、返回钱包地址信息
     * @param walletInfoDto
     * @return
     */
    @Transactional
    @Override
    public String saveWallet(WalletInfoDto walletInfoDto) {

        //获取当前登录用户
        AuthenticationInfo authenticationInfo = authenticationContext.currentUser();
        String userId = authenticationInfo.getId();
        String phone = authenticationInfo.getPhone();
        //创建钱包
        Credentials credentials = EwalletWalletUtil.createWallet();
        //获取私钥
        String privateKey = Numeric.toHexStringWithPrefix(credentials.getEcKeyPair().getPrivateKey());

        //获取钱包地址
        String address = credentials.getAddress();

        //获取keystore文件
        String keystore = EwalletWalletUtil.exportKeyStore(credentials.getEcKeyPair());

        //创建钱包
        WalletInfoDo walletInfoDo = BeanUtil.copyProperties(walletInfoDto, WalletInfoDo.class);
        walletInfoDo.setWalletName(phone);
        //交易密码加密
        walletInfoDo.setTransPwd(BCryptPasswordEncoder.getInstance().encode(walletInfoDo.getTransPwd()));
        walletInfoDo.setWalletType(EwalletWalletConstant.WALLET_TYPE_PRIVATE);
        walletInfoDo.setWalletAddress(address);
        walletInfoDo.setSecretKey(DesUtil.init().encryptHex(privateKey));
        walletInfoDo.setKeyStore(DesUtil.init().encryptHex(keystore));
        walletInfoDao.insertWallefInfo(walletInfoDo);

        //创建USDT账户-资产账户
        accountInfoService.saveAccountInfoDo(EwalletWalletConstant.MONEY_TYPE_USDT, EwalletWalletConstant.ACCOUNT_NAME_USDT+"-可用", walletInfoDo.getWalletAddress(), ACCOUNT_TYPE_AVAILABLE);

        //创建USDT账户-链上资产账户
        accountInfoService.saveAccountInfoDo(EwalletWalletConstant.MONEY_TYPE_USDT, EwalletWalletConstant.ACCOUNT_NAME_USDT+"-链上资产", walletInfoDo.getWalletAddress(), ACCOUNT_TYPE_WEB);

        //创建SHQC账户-资产账户
        accountInfoService.saveAccountInfoDo(EwalletWalletConstant.MONEY_TYPE_SHQC, EwalletWalletConstant.ACCOUNT_NAME_SHQC+"-可用", walletInfoDo.getWalletAddress(), ACCOUNT_TYPE_AVAILABLE);

        //创建SHQC账户-链上资产账户
        accountInfoService.saveAccountInfoDo(EwalletWalletConstant.MONEY_TYPE_SHQC, EwalletWalletConstant.ACCOUNT_NAME_SHQC+"-链上资产", walletInfoDo.getWalletAddress(), ACCOUNT_TYPE_WEB);

        //创建SHQC账户-理财账户
        accountInfoService.saveAccountInfoDo(EwalletWalletConstant.MONEY_TYPE_SHQC, EwalletWalletConstant.ACCOUNT_NAME_SHQC+"-理财", walletInfoDo.getWalletAddress(), EwalletWalletConstant.ACCOUNT_TYPE_REGULAR);

        //创建SHQC账户-天天盈账户
        accountInfoService.saveAccountInfoDo(EwalletWalletConstant.MONEY_TYPE_SHQC, EwalletWalletConstant.ACCOUNT_NAME_SHQC+"-天天盈", walletInfoDo.getWalletAddress(), EwalletWalletConstant.ACCOUNT_TYPE_CURRENT);

        //关联用户信息
        userWalletRelService.saveUserWalletRel(userId, address);

        return address;
    }

    @Override
    public WalletShqcAccountInfoDto getWalletShqcAccountInfo() {

        WalletShqcAccountInfoDto walletShqcAccountInfoDto = new WalletShqcAccountInfoDto();

        UserWalletRelDto userWalletRelDto = userWalletRelService.getUserWalletRel();
        if (null == userWalletRelDto) {
            return walletShqcAccountInfoDto;
        }

        String address = userWalletRelDto.getWalletAddress();

        walletShqcAccountInfoDto.setWalletAddress(address);

        //查询SHQC账户信息
        AccountInfoDto shqcAccountInfo = accountInfoService.selectAccountByWalletAddMoneyTypeId(address, EwalletWalletConstant.MONEY_TYPE_SHQC,ACCOUNT_TYPE_AVAILABLE);
        walletShqcAccountInfoDto.setAccountId(shqcAccountInfo.getAccountId());
        walletShqcAccountInfoDto.setShqcUnit(shqcAccountInfo.getMoneyTypeUnit());
        walletShqcAccountInfoDto.setContractAddress(shqcAccountInfo.getContractAddress());
        //数据精度
        BigDecimal unit = BigDecimal.valueOf(Integer.valueOf(shqcAccountInfo.getMoneyTypeUnit()));
        //可用资产
        walletShqcAccountInfoDto.setAvailableShqc(EwalletWalletUtil.toUpperWei(shqcAccountInfo.getMoneyAmount(), unit));

        //理财账户资产
        BigDecimal finaMoneyAmount = accountInfoService.selectFinaMoneyAmount(address, EwalletWalletConstant.MONEY_TYPE_SHQC);
        //冻结数量
        walletShqcAccountInfoDto.setFrozenShqc(EwalletWalletUtil.toUpperWei(finaMoneyAmount, unit));
        //shqc总量
        walletShqcAccountInfoDto.setTotalShqc(EwalletWalletUtil.toUpperWei(shqcAccountInfo.getMoneyAmount().add(finaMoneyAmount), unit));

        return walletShqcAccountInfoDto;
    }

    @Override
    public WalletUsdtAccountInfoDto getWalletUsdtAccountInfo() {
        WalletUsdtAccountInfoDto walletUsdtAccountInfoDto = new WalletUsdtAccountInfoDto();
        UserWalletRelDto userWalletRelDto = userWalletRelService.getUserWalletRel();
        if (null == userWalletRelDto) {
            return walletUsdtAccountInfoDto;
        }

        String address = userWalletRelDto.getWalletAddress();
        //查询USDT账户信息
        AccountInfoDto usdtAccountInfo = accountInfoService.selectAccountByWalletAddMoneyTypeId(address, EwalletWalletConstant.MONEY_TYPE_USDT,ACCOUNT_TYPE_AVAILABLE);
        walletUsdtAccountInfoDto.setAccountId(usdtAccountInfo.getAccountId());
        walletUsdtAccountInfoDto.setWalletAddress(usdtAccountInfo.getWalletAddress());
        walletUsdtAccountInfoDto.setUsdtUnit(usdtAccountInfo.getMoneyTypeUnit());
        walletUsdtAccountInfoDto.setContractAddress(usdtAccountInfo.getContractAddress());

        //数据精度
        BigDecimal unit = BigDecimal.valueOf(Integer.valueOf(usdtAccountInfo.getMoneyTypeUnit()));

        //USDT资产总量 = 数据库存量
        BigDecimal totalUsdt = usdtAccountInfo.getMoneyAmount();

        walletUsdtAccountInfoDto.setTotalUsdt(EwalletWalletUtil.toUpperWei(totalUsdt, unit));

        return walletUsdtAccountInfoDto;
    }

    @Override
    public List<WalletAccountInfoDto> getAllWalletUsdtAccount() {
        return BeanUtil.listCopyProperties(walletInfoDao.selectAllWalletUsdtAccount(null), WalletAccountInfoDto.class);
    }

    @Override
    public WalletAccountInfoDto getWalletAccountByAddressAndMoneyType(String address, String moneyTypeId, String accountType) {
        List<WalletAccountInfoDoo> list = walletInfoDao.selectAllWalletAccountByAddress(address);
        if (CollectionUtil.isNotEmpty(list)) {
            List<WalletAccountInfoDoo> wList = list.stream().filter(item -> moneyTypeId.equals(item.getMoneyTypeId()) && accountType.equals(item.getAccoutType())).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(wList)) {
                return BeanUtil.copyProperties(wList.get(0), WalletAccountInfoDto.class);
            }
        }
        return null;
    }

    @Override
    public List<WalletInfoDo> getAllByWalletType() {
        List<WalletInfoDo> walletInfoDos = walletInfoDao.getAllByWalletType();
        return walletInfoDos;
    }

    @Override
    public Boolean checkTransPwd(String transPwd) {
        //获取当前登录用户
        UserWalletRelDto userWalletRelDto = userWalletRelService.getUserWalletRel();
        if (null != userWalletRelDto) {
            WalletAccountInfoDto walletAccountInfoDto = getWalletAccountByAddressAndMoneyType(userWalletRelDto.getWalletAddress(), EwalletWalletConstant.MONEY_TYPE_USDT, ACCOUNT_TYPE_AVAILABLE);
            if (null != walletAccountInfoDto && BCryptPasswordEncoder.getInstance().matches(transPwd, walletAccountInfoDto.getTransPwd())) {
                return true;
            }
        }
        return false;
    }

    @Override
    public List<WalletAccountInfoDto> getAllWalletAccountByAddress(String address) {
        return BeanUtil.listCopyProperties(walletInfoDao.selectAllWalletAccountByAddress(address), WalletAccountInfoDto.class);
    }


}